[译文]Python之函数式编程篇

1. 前言

编程语言支持多种方式来解决问题:

  • 过程式语言,程序是一系列的指令,来告诉计算机如何处理输入。C,Pascal,甚至Unix shell都是过程式语言。
  • 声明式语言,你描述问题,语言来考虑如何高效的解决。SQL就是一个你熟悉的声明式语言,一条SQL查询语句描述了你想要检索的数据,SQL引擎类决定是否浏览表或者使用索引,哪条子句优先执行等等。
  • 面向对象语言,操作一个对象的集合。对象有内部状态和一些方法来查询修改这些内部状态。Smalltalk和Java就是面向对象语言。C++和Python支持面向对象编程,但是并不强制你使用面向对象特性。
  • 函数式语言,将问题分解成一个函数集合。理想情况下,函数只处理输入,产生输出,没有内部状态会影响输出。有名的函数式语言包括ML家族(斯坦福ML,OCaml和其它变种)和Haskell

有些计算机语言的设计者往往会强调某一种方式去编程,这就会让你很难用其它编程方式。其他语言是多范式语言,支持多种不同编程方式。LISP,C++和Python是多范式语言。你可以使用过程式,面向对象或者函数式。在一些大型程序里,不同的部分可能会使用不同的方式;GUI可能使用面向对象,处理逻辑的部分可能是过程式或者函数式。

一些语言会非常严格,甚至不能使用赋值语句,例如a=3或者c = a + b,但是它很难避免所有的副作用。例如屏幕打印或者把文件写入磁盘都是副作用。在Python里print语句或者time.sleep(1)都没有返回有用的值,他们的调用就是为了副作用,为了向屏幕上打印文本或者中断一秒中。

Python写成函数式形式,通常很难严格避免I/O或者赋值。相反,它们只是提供一个函数式的接口,而在内部使用非函数式特性。例如,函数的实现依然会给本地变量赋值,但是不会修改全局变量或者有其他副作用。

函数式编程可以看作是面向对象编程的反面。对象有内部状态,也提供方法来修改这些内部状态,程序的组成就是为了一系列状态改变。函数式编程尽可能的避免状态改变,在函数间传递数据流。在Python里,你可能会组合两种方式,写函数并且返回对象实例。

函数式设计看起来有一些奇怪的约束。为什么要避免对象和副作用?下面是理论和实际上的有点:

  • 形式可证明
  • 模块化
  • 可组合
  • 易于调试和测试

1.1. Formal provability

1.2 模块化

1.3 方便调试和测试

1.4 组合

2 迭代器

2.1 支持迭代器的数据类型

3 Generator 和 list comprehension

4 Generator

4.1 给一个Generator传值

5 内建函数

6 Small函数和lambda表达式

7 itertools模块

7.1 创建迭代器

7.2 在元素上调用函数

7.3 选择元素

7.4 分组元素

8 functools模块

8.1 operator模块

by Jungledrum